<?php
namespace app\home\controller;

use nekoing\BaseController;
use passport\ExtendUser;
use passport\OauthLoginFactory;
use think\Session;
use nekoing\AppException;
use nekoing\ErrorCode;
use think\Validate;
use app\home\model\User;
use nekoing\Utils;
use app\home\model\AuthCode;
use app\home\model\Openid;

class Login extends BaseController
{
    protected function autoRegister(ExtendUser $extendUser)
    {
        $data = [
            'username' => $extendUser->platform . '_' . Utils::uniqid16(),
            'password' => rand(10000, 99999) . rand(10000, 99999) . rand(10000, 99999),
            'nickname' => $extendUser->nickname,
            'avatar' => $extendUser->avatar,
            'email' => '',
            'is_extend_account' => 1,
            'extend_platform' => $extendUser->platform,
            'extend_openid' => $extendUser->openid
        ];
        
        $user = new User();
        $user->save($data);
        return $user;
    }
    
    public function third($platform = null)
    {
        $scope = input('get.scope', config('oauth.default_scope'));
        
        $validate = new Validate([
            'appid' => 'require|length:6,32',
            'redirect_uri' => 'require|url'
        ]);
        if (! $validate->check($_GET)) {
            throw new AppException(ErrorCode::INVALID_PARAM, $validate->getError());
        }
        
        $originalParams = [
            'response_type' => input('get.response_type', 'code'),
            'appid' => input('get.appid'),
            'redirect_uri' => input('get.redirect_uri'),
            'state' => input('get.state', ''),
            'scope' => $scope
        ];
        
        $sessKey = 'oauth.a' . rand(100, 999);
        Session::set($sessKey, http_build_query($originalParams));
        
        $oauthLogin = OauthLoginFactory::getByPlatform($platform);
        $oauthLogin->authorize($scope, $sessKey);
    }
    
    
    public function jump($platform)
    {
        $sessKey = input('state');
        if(! $sessKey) {
            throw new AppException(ErrorCode::INVALID_PARAM);
        }
        
        $originalParams = Session::get($sessKey);
        if(! $originalParams) {
            throw new AppException(ErrorCode::INVALID_PARAM, '链接已过期');
        }
        Session::delete($sessKey);
        
        parse_str($originalParams, $originalParams);
        $oauthLogin = OauthLoginFactory::getByPlatform($platform);
        $code = $oauthLogin->parseAuthorizeCode();
        $extendToken = $oauthLogin->token($code);
        if(empty($extendToken->openid)) {
            $extendToken->openid = $oauthLogin->openid($extendToken);
        }
        
        $user = User::get([
            'is_extend_account' => 1,
            'extend_platform' => $oauthLogin->platform(),
            'extend_openid' => $extendToken->openid
        ]);
        
        if(! $user) {
            $extendUser = $oauthLogin->userinfo($extendToken);
            $user = $this->autoRegister($extendUser);
        }

        $openid = Openid::getOpenid($user->id, $originalParams['appid']);
        
        $authCode = new AuthCode();
        
        $authCode->scope = $originalParams['scope'];
        $authCode->appid = $originalParams['appid'];
        $authCode->openid = $openid;
        $authCode->redirect_uri = $originalParams['redirect_uri'];
        
        $authCode->save();
        
        switch ($originalParams['response_type']) {
            case 'code':
                $this->codeReturn($originalParams['redirect_uri'], $originalParams['state'], $authCode->code);
            default:
                throw new AppException(100004, "response_type错误");
        }
    }

    protected function codeReturn($redirectUri, $state, $code, $message = null)
    {
        $params = [
            'code' => $code,
            'state' => $state
        ];
    
        if ($message) {
            $params['msg'] = $message;
        }
    
        if ($redirectUri) {
            $redirectUri .= (strpos('?', $redirectUri) === false ? '?' : '&') . http_build_query($params);
            $this->redirect($redirectUri);
            exit();
        } else {
            throw new AppException($code, $message);
            exit();
        }
    }
}